package com.leansoft.luxun.client;
import java.io.Closeable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import com.leansoft.luxun.api.generated.QueueService;
import com.leansoft.luxun.common.exception.ConnectionRefusedException;
public abstract class AbstractClient implements Closeable {
private final Logger logger = LoggerFactory.getLogger(AbstractClient.class);
private final String host;
private final int port;
private final int soTimeoutMs;
private final int connectTimeoutMs;
private final int MaxConnectBackoffMs = 60 * 1000;
////////////////////////////////
private TTransport transport = null;
protected QueueService.Client luxunClient = null;
protected final Object lock = new Object();
private volatile boolean shutdown = false;
public AbstractClient(String host, int port) {
this(host, port, 30 * 1000);
}
public AbstractClient(String host, int port, int soTimeoutMs) {
this(host, port, soTimeoutMs, 60 * 1000);
}
public AbstractClient(String host, int port, int soTimeout, int connectTimeoutMs) {
this.host = host;
this.port = port;
this.soTimeoutMs = soTimeout;
this.connectTimeoutMs = connectTimeoutMs;
}
protected void getOrMakeConnection() {
if (luxunClient == null) {
connect();
}
}
protected void reconnect() {
disconnect();
connect();
}
protected void connect() {
long connectBackoffMs = 1;
long beginTimeMs = System.currentTimeMillis();
while(luxunClient == null && !shutdown) {
try {
TSocket socket = new TSocket(host, port, soTimeoutMs);
transport = new TFramedTransport(socket);
TProtocol protocol = new TBinaryProtocol(transport);
luxunClient = new QueueService.Client(protocol);
transport.open();
logger.info("Connected to " + host + ":" + port + " for operating");
} catch (TTransportException e) {
disconnect();
long endTimeMs = System.currentTimeMillis();
if ((endTimeMs - beginTimeMs + connectBackoffMs) > connectTimeoutMs) {
logger.error(
"Connection attempt to " + host + ":" + port + " timing out after " + connectTimeoutMs + " ms",
e);
throw new ConnectionRefusedException(host + ":" + port, e);
}
logger.error(
"Connection attempt to " + host+ ":" + port + " failed, next attempt in " + connectBackoffMs + " ms",
e);
try {
Thread.sleep(connectBackoffMs);
} catch (InterruptedException e1) {
logger.warn(e1.getMessage());
Thread.currentThread().interrupt();
}
connectBackoffMs = Math.min(10 * connectBackoffMs, MaxConnectBackoffMs);
}
}
}
protected void disconnect() {
if (transport != null) {
logger.info("Disconnecting to " + host + ":" + port);
transport.close();
transport = null;
}
luxunClient = null;
}
public void close() {
synchronized(lock) {
disconnect();
shutdown = true;
}
}
}